package cn.org.mrliu.ssm.util.web;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;

/**
 * 下载工具类
 * 
 * @author MrLiu
 *
 */
public class DownloadUtil {
	/** 默认的字符集编码 **/
	private static final String ENCODING = "UTF-8";
	/** 默认的内容类型 **/
	public static final String CONTENT_TYPE = "application/octet-stream";
	/** 以组件形式进行下载 **/
	private static final String ATTACHMENT = "attachment";
	/** 在浏览器中打开 **/
	private static final String INLINE = "inline";

	private static Logger log = Logger.getLogger(DownloadUtil.class);

	/**
	 * <code>
	 * 文件下载<br/>
	 * Example : DownloadUtil.download(new File("D:\\testDownload"), "test.rar", request, response);
	 * </code>
	 * 
	 * @param downloadDir
	 *            下载文件的父目录
	 * @param downloadFileName
	 *            下载文件名称
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public static void download(File downloadDir, String downloadFileName, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		download(downloadDir, downloadFileName, request, response, null, false);
	}

	/**
	 * <code>
	 * 文件下载<br/>
	 * Example : DownloadUtil.download(new File("D:\\testDownload"), "test.rar", request, response,"application/octet-stream");
	 * </code>
	 * 
	 * @param downloadDir
	 *            下载文件的父目录
	 * @param downloadFileName
	 *            下载文件名称
	 * @param request
	 * @param response
	 * @param contentType
	 *            内容类型,默认:application/octet-stream
	 * @throws Exception
	 */
	public static void download(File downloadDir, String downloadFileName, HttpServletRequest request,
			HttpServletResponse response, String contentType) throws Exception {
		download(downloadDir, downloadFileName, request, response, contentType, false);
	}

	/**
	 * <code>
	 * 文件下载<br/>
	 * Example : DownloadUtil.download(new File("D:\\testDownload"), "test.html", request, response,"text/html",true);
	 * </code>
	 * 
	 * @param downloadDir
	 *            下载文件的父目录
	 * @param downloadFileName
	 *            下载文件名称
	 * @param request
	 * @param response
	 * @param contentType
	 *            内容类型,默认:application/octet-stream
	 * @param isInline
	 *            true:在浏览器中打开/false:已附件的形式下载(默认)
	 * @throws Exception
	 */
	public static void download(File downloadDir, String downloadFileName, HttpServletRequest request,
			HttpServletResponse response, String contentType, boolean isInline) throws Exception {
		log.debug("----------------------------------- download -----------------------------------");
		log.debug("fileName:" + downloadFileName);
		// 处理输出的文件名称
		String outDownloadFileName = null;
		// 针对Firefox处理中文名称
		if (BrowserUtil.isFirefox(request)) {
			outDownloadFileName = new String(downloadFileName.getBytes(ENCODING), "iso-8859-1");
		} else {
			outDownloadFileName = URLEncoder.encode(downloadFileName, ENCODING);
		}
		log.debug("outFileName:" + outDownloadFileName);

		// 设置内容类型
		if (contentType == null || contentType.trim().equals("")) {
			contentType = CONTENT_TYPE;
		}
		log.debug("contentType:" + contentType);

		// 设置下载类型,默认为附件
		String contentDisposition = ATTACHMENT;
		if (isInline) {
			contentDisposition = INLINE;
		}
		log.debug("contentDisposition:" + contentDisposition);

		// 禁止缓存
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "No-cache");
		response.setDateHeader("Expires", 0);

		// 设置字符集编码
		response.setCharacterEncoding(ENCODING);
		// 设置内容类型
		String responseContentType = contentType + "; charset=" + ENCODING;
		log.debug("responseContentType:" + responseContentType);
		response.setContentType(responseContentType);
		// 设置头信息
		String responseContentDisposition = contentDisposition + ";filename=" + outDownloadFileName;
		log.debug("responseContentDisposition:" + responseContentDisposition);
		response.setHeader("Content-Disposition", responseContentDisposition);
		OutputStream os = null;
		try {
			os = response.getOutputStream();
			File file = new File(downloadDir, downloadFileName);
			log.debug("downloadFile:" + file);
			os.write(FileUtils.readFileToByteArray(file));
			os.flush();
			log.info("文件下载成功! " + file);
		} catch (IOException e) {
			log.error("文件下载失败!", e);
			e.printStackTrace();
		} finally {
			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
				}
			}
		}
		log.debug("--------------------------------------------------------------------------------");
	}
}
